//package com.game.cluster;
//
//
//import java.io.File;
//import java.util.ArrayList;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.Set;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.concurrent.TimeUnit;
//import java.util.concurrent.atomic.AtomicBoolean;
//
//import com.game.config.NodeConfig;
//import com.game.curator.MarsNode;
//import com.game.curator.NodeManager;
//import com.game.curator.NodeType;
//import com.game.message.SwitchNodeMessage;
//import com.game.net.Connect;
//import com.game.net.NetAddress;
//import com.game.net.NettyServer;
//import com.game.netty.ConnectPool;
//import com.game.protobuf.PFSession;
//import com.game.timer.TimerCenter;
//import com.game.timer.TimerEvent;
//import com.game.timer.TimerListener;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.CommandLineRunner;
//import org.springframework.context.ApplicationEvent;
//import org.springframework.context.ApplicationListener;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.event.ContextRefreshedEvent;
//import org.springframework.core.annotation.Order;
//import org.springframework.stereotype.Component;
//
//@Component
//@Order(1)
//public class ClusterSystem implements MarsNodeListener, ApplicationListener<ContextRefreshedEvent>, CommandLineRunner, TimerListener {
//    public static ClusterSystem system;
//
//    private Logger log = LoggerFactory.getLogger(getClass());
//
//    private Map<MarsNode, ClusterClient> clusterClientMap = new HashMap<>();
//
//    private Map<String, PFSession> sessionMap = new ConcurrentHashMap<>();
//
//    private ClusterMessageDispacher clusterMessageDispacher;
//
//    private ClusterConnectInitializer initializer;
//
//    private ClusterConnectWorkPoolInitializer workPoolInitializer;
//
//    private Map<Integer, List<MarsNode>> micserviceIndexs = new HashMap<>();
//
//    @Autowired
//    public NodeManager nodeManager;
//
//    @Autowired
//    public MarsCurator marsCurator;
//
//    @Autowired
//    public NodeConfig nodeConfig;
//
//    @Autowired(required = false)
//    public TimerCenter timerCenter;
//
//    @Bean
//    public ClusterMessageDispacher clusterMessageDispacher() {
//        if (NodeType.GATE.toString().equals(this.nodeManager.nodeConfig.getType()))
//            return this.clusterMessageDispacher = (ClusterMessageDispacher)new GateClusterMessageDispacher(this);
//        return this.clusterMessageDispacher = new ClusterMessageDispacher(this);
//    }
//
//    @Bean
//    public ClusterConnectInitializer createClusterConnectInitializer() {
//        this.initializer = new ClusterConnectInitializer(this.clusterMessageDispacher);
//        this.workPoolInitializer = new ClusterConnectWorkPoolInitializer(this.clusterMessageDispacher);
//        return this.initializer;
//    }
//
//    public Map<String, PFSession> sessionMap() {
//        return this.sessionMap;
//    }
//
//    public PFSession removeSession(String sessionId) {
//        return this.sessionMap.remove(sessionId);
//    }
//
//    public void switchNode(PFSession pfSession, MarsNode marsNode) {
//        this.log.info("切换节点，sessionID{},toNode={}", pfSession.sessionId(), marsNode.getNodePath());
//        try {
//            SwitchNodeMessage switchNodeMessage = new SwitchNodeMessage(pfSession.sessionId(), marsNode.getNodePath(), pfSession.userId);
//            pfSession.send2Gate(switchNodeMessage);
//            this.sessionMap.remove(pfSession.sessionId());
//        } catch (Exception e) {
//            this.log.warn("节点异常", e);
//        }
//    }
//
//    public MarsNode switchNode(PFSession pfSession, NodeType nodeType) {
//        try {
//            MarsNode marsNode = randomMarsNode(nodeType, pfSession.getAddress().getHost(), pfSession.userId);
//            switchNode(pfSession, marsNode);
//            return marsNode;
//        } catch (Exception e) {
//            this.log.warn("节点异常", e);
//            return null;
//        }
//    }
//
//    public MarsNode switchNode(PFSession pfSession, String nodePath) {
//        try {
//            MarsNode marsNode = getNode(nodePath);
//            switchNode(pfSession, marsNode);
//            return marsNode;
//        } catch (Exception e) {
//            this.log.warn("节点异常", e);
//            return null;
//        }
//    }
//
//    public String getNodePath() {
//        return this.nodeManager.getMarNodePath(this.nodeConfig.getType(), this.nodeConfig.getName());
//    }
//
//    public ClusterClient getByNodeType(NodeType nodeType, String ip, long id) {
//        MarsNode randomOneMarsNode = randomMarsNode(nodeType, ip, id);
//        if (randomOneMarsNode == null)
//            return null;
//        return this.clusterClientMap.get(randomOneMarsNode);
//    }
//
//    public MarsNode randomMarsNode(NodeType nodeType, String ip, long id) {
//        MarsNode marsNode = this.nodeManager.getMarNode(nodeType);
//        if (marsNode == null || !marsNode.hasChildren()) {
//            this.log.warn("node not found or not has children,tpye is {}", nodeType);
//            return null;
//        }
//        return marsNode.randomOneMarsNodeWithWeight(ip, id);
//    }
//
//    public List<ClusterClient> getAllGate() {
//        List<ClusterClient> clusterClients = new ArrayList<>();
//        this.clusterClientMap.values().forEach(clusterClient -> {
//            if (NodeType.GATE.toString().equals(clusterClient.getType()))
//                clusterClients.add(clusterClient);
//        });
//        return clusterClients;
//    }
//
//    public MarsNode getNode(String path) {
//        if (path == null) {
//            this.log.warn("节点查找异常，path=null");
//            return null;
//        }
//        return this.marsCurator.getMarsNode(path);
//    }
//
//    public ClusterClient getClusterByPath(String path) {
//        MarsNode marsNode = this.marsCurator.getMarsNode(path);
//        if (marsNode == null) {
//            this.log.warn("node not found ,path is {}", path);
//            return null;
//        }
//        return this.clusterClientMap.get(marsNode);
//    }
//
//    public ConnectPool getMarsConnectPool(NetAddress netAddress) {
//        return (new ConnectPool(netAddress, this.initializer)).init().start(this.timerCenter);
//    }
//
//    public void startClusterServer() {
//        NetAddress netAddress = this.nodeConfig.getTcpAddress();
//        NettyServer nettyServer = new NettyServer(netAddress.getPort(), this.nodeConfig.workPool ? this.workPoolInitializer : this.initializer);
//        nettyServer.setName("tcp-nio-" + netAddress.getPort());
//        nettyServer.start();
//    }
//
//    private void nodeAdd(MarsNode marsNode) {
//        ClusterClient clusterClient = this.clusterClientMap.get(marsNode);
//        if (clusterClient != null)
//            clusterClient.shutdown();
//        this.clusterClientMap.put(marsNode, new ClusterClient(marsNode, this));
//        Set<Integer> micMessageTypes = marsNode.getNodeConfig().getMicserviceMessageTypes();
//        if (micMessageTypes != null && !micMessageTypes.isEmpty())
//            micMessageTypes.forEach(messageType -> {
//                List<MarsNode> marsNodes = this.micserviceIndexs.computeIfAbsent(messageType, ());
//                if (!marsNodes.contains(marsNode))
//                    marsNodes.add(marsNode);
//            });
//    }
//
//    private void nodeRemove(MarsNode marsNode) {
//        ClusterClient clusterClient = this.clusterClientMap.remove(marsNode);
//        if (clusterClient != null)
//            clusterClient.shutdown();
//        Set<Integer> micMessageTypes = marsNode.getNodeConfig().getMicserviceMessageTypes();
//        if (micMessageTypes != null && !micMessageTypes.isEmpty())
//            micMessageTypes.forEach(messageType -> {
//                List<MarsNode> marsNodes = this.micserviceIndexs.get(messageType);
//                if (marsNodes != null && marsNodes.contains(marsNode)) {
//                    marsNodes.remove(marsNode);
//                    if (marsNodes.isEmpty())
//                        this.micserviceIndexs.remove(messageType);
//                }
//            });
//    }
//
//    public Connect micserviceAllot(ClusterClient currentClient, int messageType) throws InterruptedException {
//        List<MarsNode> micserviceNodes = this.micserviceIndexs.get(Integer.valueOf(messageType));
//        if (micserviceNodes == null || micserviceNodes.isEmpty())
//            return null;
//        if (micserviceNodes.contains(currentClient.marsNode))
//            return null;
//        int index = (int)(Math.random() * micserviceNodes.size());
//        MarsNode marsNode = micserviceNodes.get(index);
//        ClusterClient clusterClient = this.clusterClientMap.get(marsNode);
//        if (clusterClient != null)
//            return clusterClient.getConnect();
//        return null;
//    }
//
//    public void nodeChange(MarsNodeListener.NodeChangeType nodeChangeType, MarsNode marsNode) {
//        this.log.debug("集群节点信息修改，nodePath={}", marsNode.getNodePath());
//        switch (nodeChangeType) {
//            case NODE_ADD:
//                nodeAdd(marsNode);
//                break;
//            case NODE_REMOVE:
//                nodeRemove(marsNode);
//                break;
//        }
//    }
//
//    public void run(String... args) throws Exception {
//        system = this;
//        startClusterServer();
//        this.marsCurator.addMarsNodeListener(this);
//        if (this.timerCenter != null)
//            this.timerCenter.add((new TimerEvent(this, "ClusterSystem", 1)).setInitTime(10).withTimeUnit(TimeUnit.MINUTES));
//    }
//
//    private static final AtomicBoolean created = new AtomicBoolean(false);
//
//    private void writePidFile() {
//        if (created.compareAndSet(false, true))
//            try {
//                File pidFile = new File("PID");
//                this.log.info("PID + pidFile.getAbsolutePath());
//                (new ApplicationPid()).write(pidFile);
//                pidFile.deleteOnExit();
//            } catch (Exception ex) {
//                String message = String.format("Cannot create pid file %s", new Object[] { "PID" });
//                this.log.warn(message, ex);
//            }
//    }
//
//    public void onApplicationEvent(ContextRefreshedEvent event) {
//        writePidFile();
//    }
//
//    @Override
//    public void onTimer(TimerEvent e) {
//        if ("ClusterSystem".equals(e.getParameter())) {
//            this.log.info("{}{}", Integer.valueOf(this.nodeConfig.weight), Integer.valueOf(this.sessionMap.size()));
//            if (this.nodeConfig.weight == 0 && this.sessionMap.isEmpty())
//                System.exit(0);
//        }
//    }
//
//
//
//}
